package com.kawins.util.colle;

import com.kawins.util.bean.BeanUtil;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.comparators.ComparableComparator;

import java.text.NumberFormat;
import java.util.*;

import static org.apache.commons.collections.ComparatorUtils.nullLowComparator;
import static org.apache.commons.collections.ComparatorUtils.reversedComparator;

/**
 * @author rankai
 *         createTime 2017-10-2017/10/31 17:35
 */
public class ListKit {

    /**
     * 获取集合对象中某个字段值的集合
     *
     * @param field
     * @param targetList
     * @param <T>
     * @return
     */
    public static <T> Set<Object> listField2Set(String field, List<T> targetList) {
        Set<Object> set = new HashSet<>(0);
        for (T t : targetList) {
            Object fieldValue = BeanUtil.getFieldValue(t, field);
            if (fieldValue != null) {
                set.add(fieldValue.toString());
            }
        }
        return set;
    }

    /**
     * 构建
     *
     * @param <T>
     */
    public static class ArrayList<T> extends java.util.ArrayList<T> {
        public static <T> ArrayList build() {
            return new ArrayList<T>();
        }

        public ArrayList<T> adds(T value) {
            super.add(value);
            return this;
        }
    }

    /**
     * 构建
     *
     * @param <T>
     */
    public static class LinkedList<T> extends java.util.LinkedList<T> {
        public static <T> LinkedList build() {
            return new LinkedList<T>();
        }

        public LinkedList<T> adds(T value) {
            super.add(value);
            return this;
        }
    }

    /**
     * 构建
     *
     * @param <T>
     */
    public static class LinkedHashSet<T> extends java.util.LinkedHashSet<T> {
        public static <T> LinkedHashSet build() {
            return new LinkedHashSet<T>();
        }

        public LinkedHashSet<T> adds(T value) {
            super.add(value);
            return this;
        }
    }

    /**
     * 排序
     */
    public static class ListSort {

        public static final int ASC = 0;//正序

        public static final int DESC = 1;//倒序

        /**
         * list按照对象指定字段排序
         *
         * @param targetList 目标排序List
         * @param key        排序字段(map中key值)
         * @param sortMode   排序方式（0 正序， 1 倒序）
         * @param <T>        范型
         */
        public static <T> void sortMap(List<T> targetList, final String key, final Integer sortMode) {
            Comparator comparator = ComparableComparator.getInstance();
            comparator = nullLowComparator(comparator);  //允许null
            if (sortMode.equals(DESC)) {
                comparator = reversedComparator(comparator); //逆序
            }
            targetList.sort(new BeanComparator(key, comparator));
        }

        /**
         * 多字段排序
         *
         * @param targetList 目标排序List
         * @param orderMap   k -> 排序字段 v -> 排序方式（0 正序， 1 倒序）
         * @param <T>        类型
         */
        public static <T> void sortMap(List<T> targetList, final LinkedHashMap<String, Integer> orderMap) {
            orderMap.forEach((k, v) -> sortMap(targetList, k, v));
            targetList.sort((a, b) -> {
                int ret = 0;
                for (Map.Entry<String, Integer> entry : orderMap.entrySet()) {
                    ret = compareObject(entry.getKey(), entry.getValue().equals(ASC), a, b);
                    if (ret != 0) {
                        break;
                    }
                }
                return ret;
            });
        }

        /**
         * 对2个对象按照指定属性名称进行排序
         *
         * @param sortName 属性名称
         * @param isAsc    true升序，false降序
         * @param fieldOne 属性1
         * @param fieldTwo 属性2
         * @return 比较结果
         */
        private static <E> int compareObject(final String sortName, final boolean isAsc, E fieldOne, E fieldTwo) {
            int ret;
            Object value1 = BeanUtil.getFieldValue(fieldOne, sortName);
            Object value2 = BeanUtil.getFieldValue(fieldTwo, sortName);
            if (value1 == null && value2 != null) {
                return isAsc ? -1 : 1;
            } else if (value1 != null && value2 == null) {
                return isAsc ? 1 : -1;
            } else if (value1 == null) {//全部为null
                return 0;
            }
            String str1 = value1.toString();
            String str2 = value2.toString();
            if (value1 instanceof Number && value2 instanceof Number) {
                int maxLen = Math.max(str1.length(), str2.length());
                str1 = addZero2Str((Number) value1, maxLen);
                str2 = addZero2Str((Number) value2, maxLen);
            } else if (value1 instanceof Date && value2 instanceof Date) {
                long time1 = ((Date) value1).getTime();
                long time2 = ((Date) value2).getTime();
                int maxLen = Long.toString(Math.max(time1, time2)).length();
                str1 = addZero2Str(time1, maxLen);
                str2 = addZero2Str(time2, maxLen);
            }
            if (isAsc) {
                ret = str1.compareTo(str2);
            } else {
                ret = str2.compareTo(str1);
            }
            return ret;
        }

        /**
         * 给数字对象按照指定长度在左侧补0.
         * <p>
         * 使用案例: addZero2Str(11,4) 返回 "0011", addZero2Str(-18,6)返回 "-000018"
         *
         * @param numObj 数字对象
         * @param length 指定的长度
         * @return 字符串
         */
        private static String addZero2Str(Number numObj, int length) {
            NumberFormat nf = NumberFormat.getInstance();
            // 设置是否使用分组
            nf.setGroupingUsed(false);
            // 设置最大整数位数
            nf.setMaximumIntegerDigits(length);
            // 设置最小整数位数
            nf.setMinimumIntegerDigits(length);
            return nf.format(numObj);
        }
    }
}
